<template>
  <div class="detail-card">
    <h4 v-if="title">{{ title }}</h4>
    <div style="height: 12px"></div>
    <div class="edit" v-if="instance.editButton" v-for="item in instance.editButton(false)">
      <component :is="item"></component>
    </div>
    <div class="layout">
      <template v-for="label in labels">
        <div v-if="label && !label.show || label.show({ data, type: 'detail', isPhone: false })" class="detail"
          :style="{ width: computedWidth(label.formWidth) || cover, marginBottom: instance.spance + 'px', }">
          <div class="title" :style="'min-width:' + instance.label_width">
            {{ label.label }}:
          </div>
          <div style="min-width: 6px"></div>
          <div style="padding-right: 12px; word-break: break-all">
            <div v-if="label.type === 'html'"
              v-html="label.hformatter({ prop: label.prop as keyof T & string, data, value: data[label.prop as keyof T & string] })">
            </div>
            <component v-else-if="label.type === 'customize'" :is="renderFormatter(toValue(data), label)"></component>
            <component v-else :is="detailRender.render(toValue(data), label)"></component>
          </div>
        </div>
      </template>
    </div>
    <slot></slot>
  </div>
</template>

<script lang="ts" setup generic="T extends Record<string, any>">
import type { interCustomize, interForm, interFormBase } from "@b/model/base/type";
import { Form } from "@b/model/base/form";
import { h, isVNode, reactive, computed, toValue } from "vue";
import { DetailRender } from "./render_item"

interface prop {
  instance: Form<T>;
  label_prop?: string;
  cover?: string;
  title?: string;
}
let v: any = 0;
const { instance, cover = "33%", label_prop = "labels" } = defineProps<prop>();
//@ts-ignore
const l = instance[label_prop] as { [key in keyof T & string]?: interForm<T, key> }
if (!l) throw new Error('bDetail 组件需要 labels 属性')
const labels = computed(() => Object.values(l).sort((a, b) => (a.sortBy || Infinity) - (b.sortBy || Infinity)))
const data = computed(() => instance.data);
const detailRender = new DetailRender<T, keyof T & string>();
const cache: Partial<T> = reactive({});
const computedWidth = (width?: string | number) => typeof width === 'number'
  ? width + 'px'
  : width;
const renderFormatter = (
  data: T,
  item: interFormBase<T, keyof T & string> & interCustomize<T, keyof T & string>
) => {
  if (!item.formatter) return h("div");
  const prop = item.prop as keyof T & string;
  if (cache[prop]) {
    v = cache[prop] as any;
  } else {
    v = item.formatter({ data, prop, value: data[prop] })
  }
  if (v instanceof Promise) {
    v.then((res) => {
      cache[prop] = res;
    });
    return h("div");
  } else {
    if (isVNode(v)) {
      return v;
    } else {
      return h("div", {}, v || item.default);
    }
  }
}
</script>

<style scoped>
.edit {
  display: flex;
  justify-content: flex-end;
  align-items: center;
  padding: 0 24px;
}

.border {
  padding: 10px;
}

.mini .el-form-item {
  width: v-bind(cover);
  margin-right: 0;
}

.detail-card {
  --item-bottom: 16px;
  position: relative;
  border-radius: 10px;
  background: var(--el-bg-color);
  overflow: hidden;
}

.detail-card+.detail-card {
  border-radius: 12px;
}

.layout {
  display: flex;
  flex-wrap: wrap;
  padding: 0 20px;
  font-size: var(--el-font-size-base);
}

.layout .title {
  color: var(--el-text-color-regular);
  white-space: nowrap;
  text-align: left;
}

.layout>div {
  min-width: v-bind("cover");
  display: flex;
  align-items: flex-start;
}
</style>
